package com.chenxiao.datasource.mainsource.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.apache.ibatis.mapping.DatabaseIdProvider;
import org.apache.ibatis.mapping.VendorDatabaseIdProvider;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.Properties;

/**
 * @Author: CX
 * @Date: Created in  2023/12/06 21:43
 * @version: v1.0
 * @Description: TODO
 **/
@Configuration
@MapperScan(basePackages = {"com.chenxiao.datasource.mainsource.mapper"},
        sqlSessionFactoryRef = "mainSqlSessionFactory")
public class DataSourceConfig {

    /**
     * mapper文件的相对路径
     */
    private static final String MAPPER_LOCATION = "classpath:mybatis/mainsource/mapper/**/*.xml";

    @Value("${main.jdbc.url}")
    private String url;

    @Value("${main.jdbc.username}")
    private String username;

    @Value("${main.jdbc.password}")
    private String password;

    @Value("${main.jdbc.driver}")
    private String driver;

    @Value("${main.jdbc.initialSize}")
    private int initialSize;

    @Value("${main.jdbc.minIdle}")
    private int minIdle;

    @Value("${main.jdbc.maxActive}")
    private int maxActive;

    @Value("${main.jdbc.maxWait}")
    private long maxWait;

    /**
     * 主数据源使用@Primary注解进行标识
     */
    @Bean(name = "mainDataSource")
    public DataSource mainDataSource() {
        DruidDataSource druidDataSource = new DruidDataSource();

        // 配置基本属性
        druidDataSource.setDriverClassName(driver);
        druidDataSource.setUsername(username);
        druidDataSource.setPassword(password);
        druidDataSource.setUrl(url);

        //初始化时建立物理连接的个数
        druidDataSource.setInitialSize(initialSize);

        //最大连接池数量
        druidDataSource.setMaxActive(maxActive);
        //最小连接池数量
        druidDataSource.setMinIdle(minIdle);
        //获取连接时最大等待时间，单位毫秒。
        druidDataSource.setMaxWait(maxWait);

        druidDataSource.setTestWhileIdle(false);
        //用来检测连接是否有效的sql
        return druidDataSource;
    }

    /**
     * 创建该数据源的事务管理
     */
    @Bean(name = "mainTransactionManager")
    public DataSourceTransactionManager mainTransactionManager() throws SQLException {
        return new DataSourceTransactionManager(mainDataSource());
    }

    /**
     * 全局配置--多类型数据库兼容
     * 设置数据库类型，properties key:数据库官方名称, value:key转小写
     * 使用：在mapper.xml中的标签中指定databaseid, mybatis会自动根据数据库匹配对应的标签
     * demo:
     * @see
     */
    @Bean(name="mainDatabaseIdProvider")
    public DatabaseIdProvider mainDatabaseIdProvider() {
        DatabaseIdProvider databaseIdProvider = new VendorDatabaseIdProvider();
        Properties p = new Properties();
        p.setProperty("Oracle", "oracle");
        p.setProperty("PostgreSQL", "postgresql");
        p.setProperty("MySQL", "mysql");
        p.setProperty("GBase ", "gbase");
        databaseIdProvider.setProperties(p);
        return databaseIdProvider;
    }

    /**
     * 创建Mybatis的连接会话工厂实例
     */
    @Bean(name = "mainSqlSessionFactory")
    public SqlSessionFactory mainSqlSessionFactory(@Qualifier("mainDataSource") DataSource ckApplyDataSource) throws Exception {
        final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        // 设置数据源bean
        sessionFactory.setDataSource(ckApplyDataSource);
        // 设置mapper文件路径
        sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(MAPPER_LOCATION));
        // 设置多类型数据库兼容
        sessionFactory.setDatabaseIdProvider(mainDatabaseIdProvider());

        return sessionFactory.getObject();
    }
}
